package com.bear.newsset.dao.sql;

import androidx.annotation.IntRange;
import androidx.annotation.NonNull;

import com.bear.newsset.dao.ImageSqlEntityDao;
import com.bear.newsset.dao.NewsDataSqlEntityDao;
import com.bear.newsset.dao.QueryNewsDataEntityDao;
import com.bear.newsset.dao.SQLAction;
import com.bear.newsset.dao.StringMapSqlEntityDao;
import com.bear.newsset.dao.entity.ImageSqlEntity;
import com.bear.newsset.dao.entity.NewsDataSqlEntity;
import com.bear.newsset.dao.entity.NewsLikeSqlEntity;
import com.bear.newsset.dao.entity.QueryNewsDataEntity;
import com.bear.newsset.dao.entity.StringMapSqlEntity;
import com.bear.newsset.entity.NewsDataEntity;
import com.bear.newsset.entity.NewsListEntity;
import com.bear.newsset.util.LogUtils;

import org.greenrobot.greendao.query.QueryBuilder;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import static com.bear.newsset.dao.sql.NewsStatusSQL.NEWS_LIKE_TYPE.ALL;

/**
 * 数据库操作 - 新闻数据类
 */
public class NewsDataSQL {
    private QueryNewsDataEntityDao mQueryDao;
    private NewsDataSqlEntityDao mNewsDao;
    private ImageSqlEntityDao mImageDao;
    private StringMapSqlEntityDao mMapDao;

    /**
     * 查询数据库中与新闻数据相关的SQL
     */
    private NewsDataSQL() {
        SQLAction action = SQLAction.getInstance();
        mQueryDao = action.getQueryNewsDataEntityDao();
        mNewsDao = action.getNewsDataSqlEntityDao();
        mImageDao = action.getImageSqlEntityDao();
        mMapDao = action.getStringMapSqlEntityDao();
    }

    public static NewsDataSQL getInstance() {
        return HANDLER.INSTANCE;
    }

    private static final class HANDLER {
        private static final NewsDataSQL INSTANCE = new NewsDataSQL();
    }

    /**
     * 插入新闻数据
     * @param entity        插入的数据
     */
    public void insertNewsDataSql(@NonNull NewsDataSqlEntity entity) {
        if( entity.getQueryId() != -1L ) mNewsDao.insertOrReplace( entity );
    }

    /**
     * 插入新闻数据Sql
     * @param entity        插入的数据
     */
    public void insertNewsDataSql(long queryId, @NonNull NewsDataSqlEntity entity) {
        if( queryId == -1L ) return;
        entity.setId( queryId );
        insertNewsDataSql( entity );
    }

    /**
     * 插入多条新闻数据Sql
     * @param entitys       新闻数据
     */
    public void insertNewsDataSql(@NonNull NewsDataSqlEntity... entitys) {
        mNewsDao.insertOrReplaceInTx( entitys );
    }

    /**
     * 插入新闻数据
     * @param mainLableId       主标签Id
     * @param childLableId      子标签Id
     * @param entity            新闻数据
     */
    public void insertNewsData(long mainLableId, long childLableId,
                               @NonNull NewsListEntity entity) {
        long queryId = String.valueOf( mainLableId + childLableId ).hashCode();
        QueryNewsDataEntity queryData = new QueryNewsDataEntity();
        NewsDataSqlEntity newsData = new NewsDataSqlEntity();
        NewsDataEntity e = entity.getItemData();
        List<ImageSqlEntity> imgSqlList = new ArrayList<>();
        List<StringMapSqlEntity> mapSqlList = new ArrayList<>();

        //图片链接
        if( e.getImageUrls() != null ) {
            for( String s : e.getImageUrls() ) {
                ImageSqlEntity img = new ImageSqlEntity();          //图片链接实体类
                img.setNewsId( e.getId() );                         //新闻唯一id
                img.setUrl( s );                                    //图片链接
                img.setCreateTime( System.currentTimeMillis() );    //创建时间
                imgSqlList.add( img );
            }
            mImageDao.insertOrReplaceInTx( imgSqlList );
        }

        //命名实体
        if( e.getEntities() != null ) {
            for(IdentityHashMap<String, String> map : e.getEntities() ) {
                for( String key : map.keySet() ) {
                    StringMapSqlEntity mapSql = new StringMapSqlEntity();
                    mapSql.setOnlyId( e.getId() );      //新闻唯一Id
                    mapSql.setKey( key );
                    mapSql.setVal( map.get( key ) );
                }
            }
            mMapDao.insertOrReplaceInTx( mapSqlList );
        }

        //新闻数据实体类
        newsData.setNewsId( e.getId() );                    //新闻唯一id
        newsData.setQueryId( queryId );                     //查询id
        newsData.setItemType( entity.getItemType() );       //图片数量类型
        newsData.setTitle( e.getTitle() );                  //新闻标题
        newsData.setUrl( e.getUrl() );                      //新闻链接
        newsData.setMainLable( e.getMainLable() );          //主标签
        newsData.setChildLable( e.getChildLable() );        //子标签
        newsData.setAppCode( e.getAppCode() );              //网站地址
        newsData.setSourceRegion( e.getSourceRegion() );    //数据源地区
        newsData.setPublishDate( e.getPublishDate() );      //公开时间
        insertNewsDataSql( newsData );

        //查询新闻数据的实体类
        queryData.setQueryId( queryId );
        queryData.setMainLableId( mainLableId );
        queryData.setChildLableId( childLableId );
        mQueryDao.insertOrReplace( queryData );
    }

    /**
     * 插入多条插入新闻数据
     * @param mainLableId       查询主标签Id
     * @param childLableId      查询子标签Id
     * @param e                 新闻数据
     */
    public void insertNewsData(long mainLableId, long childLableId, @NonNull NewsListEntity... e) {
        insertNewsData(mainLableId, childLableId, Arrays.asList(e));
    }

    /**
     * 插入多条插入新闻数据
     * @param mainLableId       查询主标签Id
     * @param childLableId      查询子标签Id
     * @param e                 新闻数据
     */
    public void insertNewsData(long mainLableId, long childLableId,
                               @NonNull List<NewsListEntity> e) {
        List<NewsListEntity> list = new CopyOnWriteArrayList<>( e );
        new Thread(() -> {
            for( NewsListEntity e1 : list ) {
                insertNewsData(mainLableId, childLableId, e1);
            }
        }).start();
    }

    /**
     * 查询新闻数据Sql
     * @param mainLableId       主标签id
     * @return                  新闻列表 sql
     */
    public QueryNewsDataEntity queryNewsDataAll(long mainLableId,
                                                       @IntRange(from = -1) int limit,
                                                       @IntRange(from = -1) int offset) {
        //查询所有包含主标签id的实体类
        QueryBuilder<QueryNewsDataEntity> query =  mQueryDao.queryBuilder()
                .where( QueryNewsDataEntityDao.Properties
                                .MainLableId.eq( mainLableId ) );
        //范围查询
        if( limit != -1 && offset != -1 ) query.limit( limit ).offset( offset );
        return query.unique();
    }

    public QueryNewsDataEntity queryNewsDataAll(long mainLableId, @IntRange(from = -1) int offset) {
        return queryNewsDataAll( mainLableId, 10, offset );
    }

    /**
     * 查询新闻id的新闻数据
     * @param newsId    新闻数据
     * @return          数据
     */
    public NewsDataSqlEntity queryNewsDataSql(@NonNull String newsId) {
        return mNewsDao.queryBuilder()
                .where( NewsDataSqlEntityDao.Properties.NewsId.eq( newsId ) )
                .unique();
    }

    /**
     * 查询账号中的新闻列表
     * @param account       账号列表
     * @return              新闻数据
     */
    public List<NewsListEntity> queryNewsDataSqlAllForAccount(@NonNull String account) {
        return queryNewsDataSqlAllForAccount( account, ALL );
    }

    public List<NewsListEntity> queryNewsDataSqlAllForAccount(@NonNull String account,
                                                              NewsStatusSQL.NEWS_LIKE_TYPE type) {
        //查询账号喜欢的新闻信息
        List<NewsLikeSqlEntity> list = NewsStatusSQL.getInstance()
                .queryNewsLikeSqlAllForAccount( account, type );
        List<NewsDataSqlEntity> dataList = new ArrayList<>();
        for( NewsLikeSqlEntity e : list ) {
            dataList.add( queryNewsDataSql( e.getNewsId() ) );
        }
        //转换成新闻数据
        return toNewsData( dataList );
    }

    /**
     * 查询新闻数据
     * @param mainLableId       主标签id
     * @param offset            开始位置，-1：查询所有
     * @return                  新闻列表
     */
    public List<NewsListEntity> queryNewsData(long mainLableId, @IntRange(from = -1) int offset) {
        //查询所有包含主标签id的实体类
        QueryNewsDataEntity queryData = queryNewsDataAll( mainLableId, offset );
        if( queryData != null ) return toNewsData( queryData.getData() );
        return new ArrayList<>();
    }

    /**
     * 转换新闻数据
         * @param list      转换的Sql新闻列表
     * @return              新闻数据
     */
    public List<NewsListEntity> toNewsData(@NonNull List<NewsDataSqlEntity> list) {
        List<NewsListEntity> newsDataList = new ArrayList<>();
        List<String> imgList;
        List<IdentityHashMap<String, String>> mapList;

        LogUtils.d("queryNewsData", "DataSize:" + list.size());
        for( NewsDataSqlEntity e : list ) {
            NewsDataEntity newsData = new NewsDataEntity();

            newsData.setId( e.getNewsId() );                    //新闻唯一Id
            newsData.setTitle( e.getTitle() );                  //新闻标题
            newsData.setUrl( e.getUrl() );                      //新闻链接
            newsData.setMainLable( e.getMainLable() );          //主标签
            newsData.setChildLable( e.getChildLable() );        //子标签
            newsData.setAppCode( e.getAppCode() );              //网站地址
            newsData.setSourceRegion( e.getSourceRegion() );    //数据源地区
            newsData.setPublishDate( e.getPublishDate() );      //公开时间

            //图片链接
            imgList = new ArrayList<>();
            for( ImageSqlEntity img : e.getImageUrlList() ) {
                imgList.add( img.getUrl() );
            }
            newsData.setImageUrls( imgList );

            //命名实体
            mapList = new ArrayList<>();
            for( StringMapSqlEntity mapSql : e.getEntitiesList() ) {
                IdentityHashMap<String, String> map = new IdentityHashMap<>();
                map.put(mapSql.getKey(), mapSql.getVal());
                mapList.add( map );
            }
            newsData.setEntities( mapList );

            //添加到新闻列表
            newsDataList.add( new NewsListEntity(e.getItemType(), newsData) );
        }

        return newsDataList;
    }

    /**
     * 查询新闻数据
     * @param mainLableId       主标签id
     * @return                  新闻列表
     */
    public List<NewsListEntity> queryNewsDataAll(long mainLableId) {
        return queryNewsData( mainLableId, -1 );
    }

}
